<template>
  <div>
    <el-card style="margin:20px 0">
      <CategorySelector :disabled="!isList"></CategorySelector>
    </el-card>

    <el-card>
      <!-- 这是属性列表的结构 -->
      <div v-show="isList">
        <el-button :disabled="!category3Id" type="primary" size="default" icon="ele-Plus" @click="showAddAttr">添加属性</el-button>
        <el-table :data="attrList" border>
          <el-table-column label="序号" type="index" width="80" align="center"></el-table-column>
          <el-table-column label="属性名称" width="150" prop="attrName"></el-table-column>
          <el-table-column label="属性值名称列表">
            <template v-slot="{ row, $index }">
              <el-tag type="success" v-for="attrValue in row.attrValueList" :key="attrValue.id">{{ attrValue.valueName
              }}</el-tag>
            </template>
          </el-table-column>
          <el-table-column label="操作" width="150">
            <template v-slot="{ row, $index }">
              <el-button type="warning" size="small" icon="ele-Edit" title="修改属性"
                @click="showUpdateAttr(row)"></el-button>

              <el-popconfirm :title="`确定要删除 ${row.attrName} 属性吗`" @confirm="deleteAttr(row)">
                <template #reference>
                  <el-button type="danger" size="small" icon="ele-Delete" title="删除属性"></el-button>
                </template>
              </el-popconfirm>

            </template>
          </el-table-column>
        </el-table>
      </div>
      <!-- 添加属性的结构 -->
      <div v-show="!isList">
        <el-form :inline="true">
          <el-form-item label="属性名">
            <el-input placeholder="请输入属性名" v-model="attrForm.attrName"></el-input>
          </el-form-item>
        </el-form>
        <el-button :disabled="!attrForm.attrName" type="primary" size="default" @click="addAttrValue">添加属性值</el-button>
        <el-button size="default" @click="isList = true">取消</el-button>
        <el-table :data="attrForm.attrValueList" border style="margin-top: 20px;">
          <el-table-column label="序号" type="index" align="center" width="80"></el-table-column>
          <el-table-column label="属性值名称">
            <template v-slot="{ row, $index }">
              <el-input @keyup.enter="toLook(row, $index, true)" ref="inputEl" size="small"
                @blur="toLook(row, $index, false)" v-if="row.isEdit" v-model="row.valueName"></el-input>
              <span style="display:inline-block;width:100%" @click="toEdit(row)" v-else>{{ row.valueName }}</span>
            </template>
          </el-table-column>
          <el-table-column label="操作">
            <template v-slot="{ row, $index }">
              <el-popconfirm :title="`确认要删除 ${row.valueName} 属性值名称吗`" @confirm="deleteAttrValue($index)">
                <template #reference>
                  <el-button type="danger" size="small" icon="ele-Delete" title="删除属性值"></el-button>
                </template>
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
        <el-button type="primary" size="default" @click="save" :disabled="!attrForm.attrValueList.length">保存</el-button>
        <el-button size="default" @click="isList = true">取消</el-button>

      </div>
    </el-card>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue"
import { ElMessage } from 'element-plus'
export default defineComponent({
  name: 'Attr',
})
</script>

<script lang="ts" setup>
import { useCategoryStore } from '@/stores/category'
import { storeToRefs } from 'pinia'
import { watch, ref, nextTick } from 'vue'
import attrApi, { type AttrListData, type AttrData, type AttrValueData } from '@/api/attr'
import cloneDeep from 'lodash/cloneDeep'
const categoryStore = useCategoryStore()
const { category1Id, category2Id, category3Id } = storeToRefs(categoryStore)
const attrList = ref<AttrListData>([])
const isList = ref(true) //控制是不是属性列表的状态数据
const inputEl = ref() //获取input的实例
// 封装函数 获取属性列表
async function getAttrList() {
  try {
    const res = await attrApi.attrInfoList(category1Id.value as number, category2Id.value as number, category3Id.value as number)
    attrList.value = res
  } catch (error) {
    ElMessage.error('获取平台属性列表失败')
  }
}

// category3Id ref对象(基本值)
// 分情况:  1有数据的 发送请求获取最新的属性列表 2无数据 把属性列表清空
watch(category3Id, (newVal) => {
  if (newVal) { //有值
    getAttrList()
  } else { //没值
    attrList.value = []
  }
  // 立即执行 从属性取到其他路由 属性组件销毁了 分类数据是存储在pinia 再次回到属性组件 分类数据还在并不涉及变化 想让人家发送请求 所以立即执行
}, { immediate: true })

// 点击添加属性展示静态
function showAddAttr() {
  // 显示添加属性的静态
  isList.value = false
  // 再次点击添加应该清除上次所添加的内容
  attrForm.value = {
    attrName: '',
    categoryId: category3Id.value as number,
    categoryLevel: 3,
    attrValueList: [],
  }
}

// 确定收集数据的格式 取决于回头咱们向后端发送请求携带的那个参数数据的格式
const attrForm = ref<AttrData>({
  attrName: '', //属性的名称
  categoryId: 0, //这个属性所属的分类的id 三级分类的id
  categoryLevel: 0, //属性所属的三级分类的级别 1 2 3 
  attrValueList: [], //属性值列表
})

// 收集属性值步骤
// 1.给tabel增加data属性 属性的值是attrValueList 但是因为是空数组 所以一项都没有
// 2.在点击添加属性值的时候 应该出来一行 增加一项数据(属性值对象)
// 其实是用到了占位思想 push了一个属性值对象 所以多了一行 属性值名称那一列应该有一个input 因为要获取到用户输入的内容 赋值之前那个空的属性值名称

// 点击添加属性值
function addAttrValue() {
  attrForm.value.attrValueList.push({
    valueName: '', //属性值的名称 是一个空字符 因为回头等着用户输入
    // 在添加属性 属性是没有id 值undefined
    // 在修改属性时 做数据的回显 row对attrForm赋值 row当中有id
    attrId: attrForm.value.id, //添加的属性值所属的属性的id
    isEdit: true
  })
  // 自动获取焦点
  nextTick(() => {
    inputEl.value.focus()
  })
}

// 点击修改显示修改属性的静态
function showUpdateAttr(row: AttrData) {
  // 显示结构
  isList.value = false
  // 数据回显
  // 因为row当中还有属性值数组 需要保证属性值数组给到attrForm时也是一个新的地址 需要深拷贝
  attrForm.value = cloneDeep(row)
  attrForm.value.attrValueList.forEach(item => {
    item.isEdit = false
  })
}

// 无论是添加属性还是修改属性 在添加属性值这次 出来的属性值名称的结构应该input(编辑模式)
// 点击修改属性 原有的属性值名称 应该是span(查看模式)
// 对于属性值名称那里的结构 不能写死是一个input 也有可能时span
// 条件渲染 应该有一个标识数据(isEdit)  应该给每一个属性值对象

// 点击查看模式变编辑模式
function toEdit(row: AttrValueData) {
  row.isEdit = true
  // 自动获取焦点
  nextTick(() => {
    inputEl.value.focus()
  })
}
// 编辑模式失去焦点变为查看模式
function toLook(row: AttrValueData, index: number, isEnter: boolean) {
  // 1.输入的属性值名称可能为空
  if (!row.valueName.trim()) { //内容为空
    isEnter ? '' : ElMessage.error('输入的属性值名称不能为空!')
    attrForm.value.attrValueList.splice(index, 1)
    return
  }
  // 2.除了自己 看是否有其他属性值名称重复的
  const flag = attrForm.value.attrValueList.some(item => {
    if (item != row) { //除了自己
      return item.valueName === row.valueName
    }
  })
  if (flag) {
    isEnter ? '' : ElMessage.error('输入的属性值名称不能重复!')
    attrForm.value.attrValueList.splice(index, 1)
    return
  }
  row.isEdit = false
}

// 点击删除属性值 不需要发送请求
function deleteAttrValue(index: number) {
  attrForm.value.attrValueList.splice(index, 1)
}

// 添加属性和修改属性的请求逻辑
async function save() {
  // 1.获取要携带参数数据(收集的数据)
  const attr = attrForm.value
  // 2.整理参数
  // 2.1 属性值名称为空去除  2.2 完成编辑模式和查看模式的 给每一个属性值增加了isEdit 人后端不要 咱们应该去除掉 2.3 必须有属性值列表
  attr.attrValueList = attr.attrValueList.filter(item => {
    if (item.valueName.trim()) { //有内容的
      delete item.isEdit
      return true
    }
  })
  if (!attr.attrValueList.length) { //空
    ElMessage.error('请确保有属性值!')
    return
  }
  // 3.发送请求
  try {
    await attrApi.saveAttrInfo(attr)
    // 4.请求成功  提示 回到属性列表界面  重新获取最新的属性列表
    ElMessage.success('保存成功')
    isList.value = true
    getAttrList()
  } catch (error) {
    // 5.请求失败
    ElMessage.error('保存失败')
  }


}

// 删除属性
async function deleteAttr(row:AttrData){
  try {
    await attrApi.deleteAttr(row.id as number)
    ElMessage.success('删除属性成功')
    getAttrList()
  } catch (error) {
    ElMessage.error('删除属性失败')
  }
}
</script>

<style scoped></style>